//
//  SEPrescriptionViewModel.swift
//  SmartEyeForDoctor
//
//  Created by QDSG on 2021/5/10.
//

import UIKit

class SEPrescriptionViewModel: SEBaseViewModel {
    var changeStatusHandler: ((SEHttpStatus) -> Void)?
    var confirmHandler: ((SEHttpStatus) -> Void)?
    
    var prescriptionList: [SEPrescriptionModel] = []
    var prescription = SEPrescriptionModel()
    
    var prescriptionMode: SEPrescriptionMode = .prescription("", "", false) {
        didSet {
            switch prescriptionMode {
            case let .prescription(inquiryId, id, isNew):
                self.isNew = isNew
                self.inquiryId = inquiryId
                self.prescription.id = id
                
                self.diagnosis = prescription.detailDtos?.first(where: { $0.isMain == 1 }) ?? SEPrescriptionDiagnosis(isMain: 1)
                self.subDiagnosisList = prescription.detailDtos?.filter { $0.isMain != 1 }.compactMap { $0 } ?? []
                self.drugList = prescription.list ?? []
            case let .template(id, _):
                if isPick {
                    self.templateId = id
                } else {
                    self.prescription.id = id
                }
                
                self.diagnosis = prescription.diagnoseTemp?.first(where: { $0.isMain == 1 }) ?? SEPrescriptionDiagnosis(isMain: 1)
                self.subDiagnosisList = prescription.diagnoseTemp?.filter { $0.isMain != 1 }.compactMap { $0 } ?? []
                self.drugList = prescription.detailTemp ?? []
            }
        }
    }
    
    var isPick: Bool = false
    private var isNew: Bool = false
    convenience init(prescription: SEPrescriptionModel, withLoading: Bool = true) {
        self.init(withLoading: withLoading)
        self.prescription = prescription
    }
    
    var inquiryId: String = ""
    var prescriptionName: String = ""
    private var templateId: String = ""
    
    var numberOfRows: Int { prescriptionList.count }
    
    func viewModel(at indexPath: IndexPath) -> SEPrescriptionViewModel {
        let viewModel = SEPrescriptionViewModel(prescription: prescriptionList[indexPath.row])
        viewModel.prescriptionName = "处方\(indexPath.row + 1)"
        return viewModel
    }
    
    var templateNameNotEmpaty: Bool {
        switch prescriptionMode {
        case .prescription: return true
        case .template:     return prescription.name?.isEmpty == false
        }
    }
    
    var mainDiagnosisNotEmpty: Bool {
        diagnosis.middle?.isEmpty == false &&
            diagnosis.prefix?.isEmpty == false &&
            diagnosis.suffix?.isEmpty == false
    }
    var recommendNotEmpaty: Bool { prescription.proposal?.isEmpty == false }
    var entrustNotEmpty: Bool { prescription.remark?.isEmpty == false }
    
    var patientSexImage: UIImage? {
        prescription.patientSex == 1 ? Asset.iconSexMale.image : Asset.iconSexFemale.image
    }
    var patientAge: String? {
        "\(prescription.patientAge ?? "")岁"
    }
    var diagnosisResult: String? {
        prescription.diagnoseName?.replacingOccurrences(of: " ", with: "-")
    }
    
    // MARK: - 新建
    
    var reviewerHidden: Bool {
        switch prescriptionMode {
        case let .prescription(_, _, isNew):
            return isNew
        case .template:
            return true
        }
    }
    
    var confirmButtonHidden: Bool {
        switch prescriptionMode {
        case let .prescription(_, _, isNew):
            return isNew ? false : prescription.status.confirmButtonHidden
        case .template:
            return false
        }
    }
    
    var canEdit: Bool {
        switch prescriptionMode {
        case let .prescription(_, _, isNew):
            return isNew ? true : prescription.status.canEdit
        case .template:
            return true
        }
    }
    
    func switchIsChildren() {
        prescription.isChild = prescription.isChild == 1 ? 0 : 1
    }
    var isChildrenStr: String { prescription.isChild == 1 ? "是" : "否" }
    
    var numberOfSectionsForNew: Int { return 6 }
    
    func numberOfRowsForNew(in section: Int) -> Int {
        switch section {
        case 1, 5:  return 1
        case 2:  return subDiagnosisList.count
        case 3:  return 2
        case 4:  return drugList.count + 1
        default: return 0
        }
    }
    
    func cellHeightForNew(at indexPath: IndexPath) -> CGFloat {
        switch indexPath.section {
        case 1, 2, 3: return 154
        case 4:       return indexPath.row == 0 ? 82 : 68
        case 5:       return 140
        default:      return 0
        }
    }
    
    func headerHeightForNew(in section: Int) -> CGFloat { section != 5 ? 50 : 0.001 }
    
    func footerHeightForNew(in section: Int) -> CGFloat { section == 4 ? 0.001 : 10 }
    
    // MARK: - 处方药品
    
    var totalPrice: String {
        let price = Double(drug.outPrice?.intValue ?? 0) * Double(drug.drugNumber?.intValue ?? 0)
        return String(format: "%.2f元", price / 100)
    }
    
    var drug = SEPrescriptionDrug()
    
    convenience init(drug: SEPrescriptionDrug) {
        self.init()
        self.drug = drug
    }
    
    var drugList = [SEPrescriptionDrug]()
    
    func insert(drug: SEPrescriptionDrug) {
        drugList.append(drug)
    }
    
    func removeDrug(at indexPath: IndexPath) {
        guard drugList.count >= indexPath.row else { return }
        drugList.remove(at: indexPath.row - 1)
    }
    
    private var listOfDrugParameters: [[String: Any]] {
        let list = drugList.filter { $0.id != nil }.compactMap { $0 }
        return list.map { model -> [String: Any] in
            return [
                "medicineId": model.medicineId ?? "",
                "name": model.name ?? "",
                "drugSpecification": model.drugSpecification ?? "",
                "drugNumber": model.drugNumber ?? "",
                "baseUnit": model.baseUnit ?? "",
                "drugFrequency": model.drugFrequency ?? "",
                "drugDose": model.drugDose ?? "",
                "dosageUnit": model.dosageUnit ?? "",
                "drugChannel": model.drugUsing ?? "",
                "drugPosition": model.drugPosition ?? "",
                "expense": model.outPrice ?? "",
            ]
        }
    }
    
    func drugViewModel(at indexPath: IndexPath) -> SEPrescriptionViewModel {
        return SEPrescriptionViewModel(drug: drugList[indexPath.row - 1])
    }
    
    // MARK: - 主次诊断
    
    private var listOfDiagnosisParameters: [[String: Any]] {
        var list = [SEPrescriptionDiagnosis](subDiagnosisList)
        list.insert(diagnosis, at: 0)
        return list.map { model -> [String: Any] in
            return [
                "isMain": model.isMain,
                "prefix": model.prefix ?? "",
                "middle": model.middle ?? "",
                "suffix": model.suffix ?? ""
            ]
        }
    }
    
    var isMainDiagnosis: Bool { diagnosis.isMain == 1 }
    
    var diagnosis = SEPrescriptionDiagnosis()
    
    var subDiagnosisList = [SEPrescriptionDiagnosis]()
    
    convenience init(diagnosis: SEPrescriptionDiagnosis) {
        self.init()
        self.diagnosis = diagnosis
    }
    
    func subDiagnosisViewModel(at indexPath: IndexPath) -> SEPrescriptionViewModel {
        return SEPrescriptionViewModel(diagnosis: subDiagnosisList[indexPath.row])
    }
    
    func addSubDiagnosis() {
        let subDiagnosis = SEPrescriptionDiagnosis()
        subDiagnosisList.append(subDiagnosis)
    }
    
    func removeSubDiagnosis(at indexPath: IndexPath) {
        guard subDiagnosisList.count > indexPath.row else { return }
        subDiagnosisList.remove(at: indexPath.row)
    }
    
    func handleDiagnosisPick(with type: SEPrescriptionDiagnosisType, at indexPath: IndexPath, value: String?) {
        switch type {
        case .prefix:
            if indexPath.section == 1 {
                diagnosis.prefix = value
            } else {
                var subDiagnosis = subDiagnosisList[indexPath.row]
                subDiagnosis.prefix = value
                subDiagnosisList[indexPath.row] = subDiagnosis
            }
        case .suffix:
            if indexPath.section == 1 {
                diagnosis.suffix = value
            } else {
                var subDiagnosis = subDiagnosisList[indexPath.row]
                subDiagnosis.suffix = value
                subDiagnosisList[indexPath.row] = subDiagnosis
            }
        case .diagnose:
            if indexPath.section == 1 {
                diagnosis.middle = value
            } else {
                var subDiagnosis = subDiagnosisList[indexPath.row]
                subDiagnosis.middle = value
                subDiagnosisList[indexPath.row] = subDiagnosis
            }
        }
    }
}

// MARK: - 网络请求

extension SEPrescriptionViewModel {
    func getListOfPrescription() {
        SEHttpManager.shared.request(SEPrescriptionAPI.listOfPrescription(inquiryId: inquiryId), model: [SEPrescriptionModel].self, completion: { (models, httpStatus) in
            switch httpStatus {
            case .success:
                self.prescriptionList = models ?? self.prescriptionList
            case .failure(let message):
                SEHUD.showError(message: message)
            case .auth: break
            }
            self.updateData?(httpStatus)
        })
    }
    
    func getDetail() {
        switch prescriptionMode {
        case let .prescription(_, _, isNew):
            if !isNew { getDetailOfPrescription() }
        case let .template(_, isNew):
            if !isNew { getDetailOfPrescriptionTemplate() }
        }
    }
    
    private func getDetailOfPrescription() {
        SEHttpManager.shared.request(SEPrescriptionAPI.detailOfPrescription(id: prescription.id ?? ""), model: SEPrescriptionModel.self, withLoading: withLoading) { (model, httpStatus) in
            switch httpStatus {
            case .success:
                self.prescription = model ?? self.prescription
                self.diagnosis = self.prescription.detailDtos?.first(where: { $0.isMain == 1 }) ?? SEPrescriptionDiagnosis(isMain: 1)
                self.subDiagnosisList = self.prescription.detailDtos?.filter { $0.isMain != 1 }.compactMap { $0 } ?? []
                self.drugList = self.prescription.list ?? []
            case .failure(let message):
                SEHUD.showError(message: message)
            case .auth: break
            }
            self.updateData?(httpStatus)
        }
    }
    
    func save() {
        switch prescriptionMode {
        case .prescription:
            savePrescription()
        case .template:
            savePrescriptionTemplate()
        }
    }
    
    private func savePrescription() {
        SEHttpManager.shared.request(SEPrescriptionAPI.savePrescription(bisId: inquiryId, id: prescription.id ?? "", isChild: prescription.isChild, proposal: prescription.proposal ?? "", remark: prescription.remark ?? "", list: listOfDrugParameters, detailVos: listOfDiagnosisParameters), model: Any.self, withLoading: withLoading) { (result, httpStatus) in
            self.confirmHandler?(httpStatus)
        }
    }
    
    func changePrescriptionStatus(_ id: String, status: SEPrescriptionStatus) {
        SEHttpManager.shared.request(SEPrescriptionAPI.changePrescriptionStatus(id: id, status: status.rawValue), model: Any.self, withLoading: withLoading) { (result, httpStatus) in
            self.changeStatusHandler?(httpStatus)
        }
    }
    
    func getListOfPrescriptionRejected(_ more: Bool) {
        page = more ? page + 1 : 1
        SEHttpManager.shared.request(SEPrescriptionAPI.listOfPrescriptionRejected(pageNum: page, pageSize: pageSize), model: SEPrescriptionList.self) { (model, httpStatus) in
            switch httpStatus {
            case .success:
                if !more {
                    self.prescriptionList = model?.list ?? self.prescriptionList
                } else {
                    self.prescriptionList.append(contentsOf: model?.list ?? [])
                }
                self.hasMore = model?.totalPage ?? 0 > self.page
            case .failure(let message):
                SEHUD.showError(message: message)
            case .auth: break
            }
            self.updateData?(httpStatus)
        }
    }
    
    func getListOfPrescriptionTemplate(_ more: Bool) {
        page = more ? page + 1 : 1
        SEHttpManager.shared.request(SEPrescriptionAPI.listOfPrescriptionTemplate(pageNum: page, pageSize: pageSize), model: SEPrescriptionList.self) { model, httpStatus in
            switch httpStatus {
            case .success:
                if !more {
                    self.prescriptionList = model?.list ?? self.prescriptionList
                } else {
                    self.prescriptionList.append(contentsOf: model?.list ?? [])
                }
                self.hasMore = model?.totalPage ?? 0 > self.page
            case .failure(let message):
                SEHUD.showError(message: message)
            case .auth: break
            }
            self.updateData?(httpStatus)
        }
    }
    
    private func getDetailOfPrescriptionTemplate() {
        SEHttpManager.shared.request(SEPrescriptionAPI.detailOfPrescriptionTemplate(id: isPick ? templateId : prescription.id ?? ""), model: SEPrescriptionModel.self, withLoading: withLoading) { model, httpStatus in
            switch httpStatus {
            case .success:
                if !self.isPick {
                    self.prescription = model ?? self.prescription
                } else {
                    if let model = model {
                        self.prescriptionMode = .prescription(self.inquiryId, self.prescription.id ?? "", self.isNew)
                        self.prescription.name = model.name
                        self.prescription.isChild = model.isChild
                        self.prescription.proposal = model.proposal
                        self.prescription.remark = model.remark
                        self.prescription.detailTemp = model.detailTemp
                        self.prescription.diagnoseTemp = model.diagnoseTemp
                    }
                }
                
                self.diagnosis = self.prescription.diagnoseTemp?.first(where: { $0.isMain == 1 }) ?? SEPrescriptionDiagnosis(isMain: 1)
                self.subDiagnosisList = self.prescription.diagnoseTemp?.filter { $0.isMain != 1 }.compactMap { $0 } ?? []
                self.drugList = self.prescription.detailTemp ?? []
            case .failure(let message):
                SEHUD.showError(message: message)
            case .auth: break
            }
            self.updateData?(httpStatus)
        }
    }
    
    private func savePrescriptionTemplate() {
        SEHttpManager.shared.request(SEPrescriptionAPI.savePrescriptionTemplate(id: prescription.id ?? "", name: prescription.name ?? "", isChild: prescription.isChild, proposal: prescription.proposal ?? "", remark: prescription.remark ?? "", diagnoseTemp: listOfDiagnosisParameters, detailTemp: listOfDrugParameters), model: Any.self, withLoading: withLoading) { result, httpStatus in
            self.confirmHandler?(httpStatus)
        }
    }
    /// 删除处方模版
    public func deleteePrescriptionTemplate(indexPath: IndexPath, successComplete: @escaping () -> Void) {
        let model = prescriptionList[indexPath.row]
        guard let id = model.id else { return }
        SEHttpManager.shared.request(SEPrescriptionAPI.deletePrescriptionTemplate(id: id), model: String.self, completion: { result, status in
            switch status {
            case .success:
                SEHUD.show(message: "删除成功")
                self.prescriptionList.remove(at: indexPath.row)
                successComplete()
            case .auth(let message), .failure(let message):
                SEHUD.showError(message: message)
            }
        })
    }
}
